namespace CRM_Perf_BenchMark
{
    using System;
    using System.Collections.Generic;
    using Microsoft.VisualStudio.TestTools.WebTesting;
    using System.Net;
    using System.Text;
    using System.Xml;

    /// <summary>
    /// 1. Starts at Sales homepage
    /// 2. Click on Accounts
	/// 3. Select Active Accounts view
	/// 4. Add random string of two characters in look for textbox and click find
    /// 5. Double click an account
    /// 6. Select Actions -> Add Activity -> Task on menu bar
    /// 7. Add random string to Subject and Description
    /// 8. Click Save & Close
    /// 9. Click Save & Close
    /// </summary>
    
    public class AddActivityToAccount : CrmWebTest
    {
        public void AddActivityToAccount_PreWebTest(object sender, PreWebTestEventArgs e)
        {
            EntityRequest er = new EntityRequest();
            er.Type = EntityNames.Users;
            er.ReturnAs = EntityNames.Users;
            er.ParentID = EntityManager.Instance.OrgId;

            System.Collections.Hashtable userProps = new System.Collections.Hashtable();
            if (e.WebTest.Context.ContainsKey("UserRole"))
            {
                userProps.Add("role", e.WebTest.Context["UserRole"]);
            }
            
            EntityRequest AccountEr = new EntityRequest();
            AccountEr.Type = EntityNames.Accounts;
            AccountEr.ParentID = Guid.NewGuid();
            AccountEr.ReturnAs = EntityNames.Accounts;

            userProps.Add(EntityNames.Accounts, new EntityRequest[] { AccountEr });

            er.Props = userProps;

            System.Collections.Hashtable Entities = EntityManager.Instance.GetEntities(er);

            user = (CRMEntity)Entities[EntityNames.Users];
            account = (CRMEntity)Entities[EntityNames.Accounts];

            e.WebTest.UserName = user["domainName"];
            e.WebTest.Password = user["userpassword"];
            
            e.WebTest.UserName = user["domainName"];
            e.WebTest.Password = user["userpassword"];
            crmServer = user["CrmServer"];
            tokenKey = EntityManager.Instance.ReadTokenKey(user["organizationid"]);
            orgId = new Guid(user["organizationid"]);
            ownerId = new Guid(user["systemuserid"]);
            regardingobjectId = new Guid(account["accountid"]);            
        }

        public void AddActivityToAccount_PostWebTest(object sender, PostWebTestEventArgs e)
        {
			try
			{
		        if (newTaskId != null)
        		{
                    Guid g = EntityManager.Instance.GetOwnerGuid(new Guid(user[EntityIDNames.User]), new Guid(user["OrganizationId"]));
					EntityManager.Instance.AddEntity(EntityNames.Tasks, g, new string[] { "OwningUser", "ActivityID" , "EntityManagerOwningUser"}, new string[] { user["systemuserid"], newTaskId, g.ToString()});
				}
			}
			finally
			{
				EntityManager.Instance.FreeEntity(user);
				EntityManager.Instance.FreeEntity(account);
			}
        }

        private void AddActivityToAccount_ValidateResponse(object sender, ValidationEventArgs e)
        {
            string ID = null;

            int idIdx = e.Response.BodyString.IndexOf(newIdMarker);
            ID = e.Response.BodyString.Substring(idIdx + (AddActivityToAccount.newIdMarker.Length), 36);
            try
            {
                ID = new Guid(ID).ToString();
            }
            catch (System.FormatException fe)
            {
                System.Diagnostics.Trace.WriteLine("Format exception: " + fe.ToString());
                e.IsValid = false;
                return;
            }
            e.IsValid = true;
        }

        public AddActivityToAccount()
        {
            WebRequest.RegisterPrefix("crm", new crmRequestFactory());
            string random = Utils.GetRandomString(2, 2);
            gridXml = GridXmlHelper.AccountPageView(-1, activeAccountView, null);
            gridXml2 = GridXmlHelper.AccountSearchView(-1, searchAccountView, random, null);

            this.Proxy = null;            
            PreWebTest += new EventHandler<PreWebTestEventArgs>(AddActivityToAccount_PreWebTest);
            PostWebTest += new EventHandler<PostWebTestEventArgs>(AddActivityToAccount_PostWebTest);
        }

        static AddActivityToAccount()
        {
        }

        public override IEnumerator<WebTestRequest> GetRequestEnumerator()
        {
            gridRefreshXml = GridXmlHelper.ActivityGridForEntityViewRefresh(-1, activityView, null, account[EntityIDNames.Account], "1");
            AppGridWebService.AppGridWebService ag;
            WebTestRequest wtr;

            this.BeginTransaction("NavAccountHomepage");

            // Get the home page
            _root_homepage_aspx hp = new _root_homepage_aspx(user);
            hp.etc = 1;
            yield return (hp);

			this.EndTransaction("NavAccountHomepage");

            if (ConfigSettings.Default.alltasks == true)
            {
                this.BeginTransaction("NavActiveAccounts");

                // Open All Accounts view
                ag = new AppGridWebService.AppGridWebService();
                wtr = null;

                try { ag.Reset(gridXml, gridId); }
                catch (crmException x)
                {
                    wtr = (CrmRequest)x.wtr;
                    wtr.Url = Utils.ReplaceServerName(wtr.Url, user);

                    string urlPath = wtr.Url.Remove(0, crmServer.Length);
                    urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

                    rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

                    headerItem = new WebTestRequestHeader();
                    headerItem.Name = "crmwrpctokentimestamp";
                    headerItem.Value = rpcInfo.timeStamp.ToString();
                    wtr.Headers.Add(headerItem);
                    headerItem = new WebTestRequestHeader();
                    headerItem.Name = "crmwrpctoken";
                    headerItem.Value = rpcInfo.token;
                    wtr.Headers.Add(headerItem);
                    wtr.Method = "Post";
                }
                yield return (wtr);

                this.EndTransaction("NavActiveAccounts");
            }

            this.BeginTransaction("SearchAccounts");

            ag = new AppGridWebService.AppGridWebService();
            wtr = null;

            try { ag.Reset(gridXml2, gridId); }
            catch (crmException x)
            {
                wtr = (CrmRequest)x.wtr;
                wtr.Url = Utils.ReplaceServerName(wtr.Url, user);

                string urlPath = wtr.Url.Remove(0, crmServer.Length);
                urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

                rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

                headerItem = new WebTestRequestHeader();
                headerItem.Name = "crmwrpctokentimestamp";
                headerItem.Value = rpcInfo.timeStamp.ToString();
                wtr.Headers.Add(headerItem);
                headerItem = new WebTestRequestHeader();
                headerItem.Name = "crmwrpctoken";
                headerItem.Value = rpcInfo.token;
                wtr.Headers.Add(headerItem);
                wtr.Method = "Post";
            }
            yield return (wtr);

            this.EndTransaction("SearchAccounts");

            this.BeginTransaction("OpenAccount");

            sfa_accts_edit_aspx dp = new sfa_accts_edit_aspx(user);
            dp.id = account["accountid"];
            yield return (dp);

            referer = dp.lastResponse.ResponseUri.AbsoluteUri;

            _forms_FormScript_js_aspx fs = new _forms_FormScript_js_aspx(user);
            fs.etc = 1;
            fs.FormType = "main";
            fs.FormName = "crmForm";
            headerItem = new WebTestRequestHeader();
            headerItem.Name = "referer";
            headerItem.Value = referer;
            fs.Headers.Add(headerItem);
            yield return (fs);

            this.EndTransaction("OpenAccount");

            this.BeginTransaction("AddActivityToAccount");
            
            activities_task_edit_aspx updateFormPage = new activities_task_edit_aspx(user);
            updateFormPage.pId = new Guid(account["accountid"]);
            updateFormPage.pType = 1;
            updateFormPage.pName = account["name"];

            yield return (updateFormPage);

            referer = updateFormPage.lastResponse.ResponseUri.AbsoluteUri;

            fs = new _forms_FormScript_js_aspx(user);
            fs.etc = 4212;
            fs.FormType = "main";
            fs.FormName = "crmForm";
            headerItem = new WebTestRequestHeader();
            headerItem.Name = "referer";
            headerItem.Value = referer;
            fs.Headers.Add(headerItem);
            yield return (fs);

            updateFormPage = new activities_task_edit_aspx(user);
            updateFormPage.pId = new Guid(account["accountid"]);
            updateFormPage.pType = 1;
            updateFormPage.pName = account["name"];

            updateFormPage.crmFormSubmitXml = EntityXmlHelper.GetCreateTaskXml(ownerId, 8, regardingobjectId, 1);
           
            rpcInfo = Utils.GenerateWRPCToken(activities_task_edit_aspx.url, user, tokenKey);
            updateFormPage.CRMWRPCToken = rpcInfo.token;
            updateFormPage.CRMWRPCTokenTimeStamp = rpcInfo.timeStamp;
            updateFormPage.crmFormSubmitMode = 1;
            updateFormPage.crmFormSubmitObjectType = 4212;
            updateFormPage.crmFormSubmitSecurity = 852023;
            updateFormPage.crmFormSubmitOnline = 1;
            updateFormPage.crmFormUserModified = true;

            updateFormPage.ValidateResponse += this.AddActivityToAccount_ValidateResponse;

            yield return (updateFormPage);

            this.EndTransaction("AddActivityToAccount");

            //get the newly created task id out of the post reply
            int idIdx = updateFormPage.lastResponse.BodyString.IndexOf(newIdMarker);
            string tempnewTaskId = updateFormPage.lastResponse.BodyString.Substring(idIdx + (AddActivityToAccount.newIdMarker.Length), 36);            
            newTaskId = new Guid(tempnewTaskId).ToString();
        }
        		
        private const string newIdMarker = @"""id=";
        private string gridXml;
        private string gridXml2;
        private string gridRefreshXml;
        private static string gridId = "crmGrid";
        private static string activeAccountView = "00000000-0000-0000-00AA-000010001002";
        private static string searchAccountView = "2D1187C4-23FE-4BB5-9647-43BB1C6DDBD1";
        private static string activityView = "00000000-0000-0000-00AA-000010001903";
        private string newTaskId = null;

        private CRMEntity user;
        private CRMEntity account;        
        private string crmServer;
        private string tokenKey;
        private string referer;
             
        private Guid orgId;
        private Guid ownerId;
        private Guid regardingobjectId;
        private WebTestRequestHeader headerItem;
        private WRPCInfo rpcInfo;
    }
}